package com.jiliason.segmentation.doMain.serviceModel.addr;

import com.google.common.collect.Lists;
import com.jiliason.segmentation.constant.enums.Addr;
import com.jiliason.segmentation.constant.enums.Strategy;
import com.jiliason.segmentation.doMain.serviceModel.SegmentModelProc;
import com.jiliason.segmentation.doMain.event.AddrDictSegment;
import com.jiliason.segmentation.doMain.event.AddrParsingSegment;
import com.jiliason.segmentation.entity.address.AddressUnitPojo;
import com.jiliason.segmentation.entity.address.FullAddressOutPojo;
import com.jiliason.segmentation.entity.address.ResultAddressPojo;
import com.jiliason.segmentation.entity.SegmentInputPojo;
import com.jiliason.segmentation.entity.splitterStrategy.StrategyInPojo;
import com.jiliason.segmentation.utils.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class FullAddress extends SegmentModelProc<ResultAddressPojo> {

    protected FullAddress() {
        super("FullAddress", Lists.newArrayList("true", "false"));
    }

    @Resource
    private AddrDictSegment dictSegment;

    @Resource
    private AddrParsingSegment parsingSegment;

    @Override
    protected boolean invalidInput(SegmentInputPojo input) {
        // 被分词对象为空白，既不合规
        return StringUtils.isBlank(input.getAddrStr());
    }

    @Override
    protected ResultAddressPojo exeSegment(SegmentInputPojo input) throws Exception {

        // 初期化被分割对象
        StrategyInPojo in = new StrategyInPojo(input.getAddrStr(), input.getAddrStr());

        // 初期化分词结果
        AddressUnitPojo[] segResults = new AddressUnitPojo[Addr.FILED_SIZE.i()];
        for (int i = 0; i < segResults.length; i++) segResults[i] = new AddressUnitPojo();

        // 分词国家
        getCN(in, segResults);

        // 地址词库分词
        dictionarySegment(in, segResults);

        if (in.endSegment()) return buildResultAddressPojo(segResults);

        // 解析分词
        parsingSegment(in, segResults);

        // 策略穷尽，将还剩下的部分投入other字段
        if (!in.endSegment()) other(in, segResults);

        return buildResultAddressPojo(segResults);
    }

    private void getCN(StrategyInPojo in, AddressUnitPojo[] segResults) {
        if (!in.getAddrStr().startsWith("中国")) return;
        // 初期化other
        segResults[Addr.OTHER.i()].setFiledValue("中国");
        in.split("中国");
    }

    @Override
    protected String buildResponse(SegmentInputPojo input, ResultAddressPojo segRes) {
        FullAddressOutPojo out = FullAddressOutPojo.builder()
                .statusCode(0)
                .labeledAddress("")
                .resultAddress(segRes).build();
        return JsonUtil.pojoToJson(out);
    }

    /**
    * @description _词库分词，仅对省份，城市，区县，乡镇进行分词
    * @param in,segResults 被分割对象，分词结果List
    * @date 2023/12/25
    * @author sjy
    */
    private void dictionarySegment(StrategyInPojo in, AddressUnitPojo[] segResults) throws Exception {
        List<AddressUnitPojo> dictRes = dictSegment.divide(in);
        for (AddressUnitPojo dictUnit : dictRes) {
            segResults[dictUnit.getFiledName().i()] = dictUnit;
        }
    }

    private void parsingSegment(StrategyInPojo in, AddressUnitPojo[] segResults) {
        List<String> dictSegRes = getDictionarySegmentRes(segResults);
        List<AddressUnitPojo> parseRes = parsingSegment.divide(in, dictSegRes);
        for (AddressUnitPojo parseUnit : parseRes) {
            segResults[parseUnit.getFiledName().i()] = parseUnit;
        }
    }

    private List<String> getDictionarySegmentRes(AddressUnitPojo[] segResults) {
        return Arrays.stream(segResults)
                .map(AddressUnitPojo::getFiledValue)
                .filter(StringUtils::isNotBlank)
                .toList();
    }

    private void other(StrategyInPojo in, AddressUnitPojo[] segResults) {
        String otherStr = Optional.ofNullable(segResults[Addr.OTHER.i()].getFiledValue()).orElse("") + in.getAddrStr();
        segResults[Addr.OTHER.i()].setFiledValue(otherStr);
    }

    private ResultAddressPojo buildResultAddressPojo(AddressUnitPojo[] segResults) {
        // 获取已经分割到的段的map
        Map<String, Object> m_filed_map = Arrays.stream(segResults)
                .filter(u -> StringUtils.equals(Strategy.M.c(), u.getSegStatus()))
                .collect(Collectors.toMap(u -> u.getFiledName().v(), AddressUnitPojo::getFiledValue));

        // 获取已分割到的段的Type的map
        Map<String, Object> t_filed_map = Arrays.stream(segResults)
                .filter(u -> StringUtils.equals(Strategy.M.c(), u.getSegStatus()))
                .filter(u -> Objects.nonNull(u.getTypeFiledName()))
                .collect(Collectors.toMap(u -> u.getTypeFiledName().v(), AddressUnitPojo::getType));

        // 合体
        m_filed_map.putAll(t_filed_map);

        // 追加other
        m_filed_map.put(Addr.OTHER.v(), segResults[Addr.OTHER.i()].getFiledValue());
        return JsonUtil.mapToPojo(m_filed_map, ResultAddressPojo.class);
    }
}
